import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class DataManager {

    private static Database database;

    static {
        boolean inputSuccess = inputFromData();
        System.out.println("被执行了");
        if (inputSuccess) {
            System.out.println("数据来自本地文件");
            Database.DatabaseInit(database);
            for (User item : database.getUserList()) {
                System.out.println(item);
            }
            database.getChoiceQuestionList().forEach(System.out::println);
            database.getTrueOrFalseQuestionList().forEach(System.out::println);
        }else try {
            System.out.println("数据来自新的temp database");
            database  = new Database("temp");
            Database.DatabaseInit(database);
            outputDataToFile(Database.DATABASE_PATH);
            throw new Exception();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public synchronized static void boot() {
        System.out.println("启动Database");
    }

    /**
     * 从数据文件导入database数据，该文件是导出生成的文件，不是自定义编写的
     * @return 导入是否成功
     */
    public synchronized static boolean inputFromData() {
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream(Database.DATABASE_PATH));
            Object o = ois.readObject();
            if (o instanceof Database) {
                database = (Database)o;
                return true;
            }
            return false;
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
            return false;
        } finally {
            try {
                if (ois != null) {
                    ois.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 从txt文件导入题目，便于快速编辑题目
     * 题目有选择题和判断题两种
     * @param txt 源txt文件
     * @throws IOException 异常
     */
    public synchronized static void inputFromTXT(File txt) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader(txt));
        String read;
        do {
            System.out.println(111);
            read = br.readLine();
            if (read != null) {
                if (read.equals("trueOrFalseQuestion")) {
                    String[] vars = new String[TrueOrFalseQuestion.LINE_NUMBER];
                    for (int i = 0; i < TrueOrFalseQuestion.LINE_NUMBER; i++) {
                        vars[i] = br.readLine().split(" ")[1];
                    }
                    TrueOrFalseQuestion trueOrFalseQuestion = new TrueOrFalseQuestion(vars);
                    System.out.println(trueOrFalseQuestion);
                    addTrueOrFalseQ(trueOrFalseQuestion);

                }
                else if (read.equals("choiceQuestion")) {
                    String[] vars = new String[ChoiceQuestion.LINE_NUMBER];
                    for (int i = 0; i < ChoiceQuestion.LINE_NUMBER; i++) {
                        vars[i] = br.readLine().split(" ")[1];
                    }
                    ChoiceQuestion choiceQuestion = new ChoiceQuestion(vars);
                    System.out.println(choiceQuestion);
                    addChoiceQ(choiceQuestion);
                }
            }
        }while (read != null);
    }

    /**
     * 将database对象导出到本地文件
     * @param dataFile 目标文件
     * @throws IOException 异常
     */
    public synchronized static void outputDataToFile(File dataFile) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(dataFile));
        oos.writeObject(database);
    }

    /**
     * 向数据库增加一个选择题
     * @param cq choice question 选择题
     */
    public synchronized static void addChoiceQ(ChoiceQuestion cq) {
        database.getChoiceQuestionList().add(cq);
        try {
            outputDataToFile(Database.DATABASE_PATH);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 向数据库增加一个判断题
     * @param tofQ true or false question 判断题
     */
    public synchronized static void addTrueOrFalseQ(TrueOrFalseQuestion tofQ) {
        database.getTrueOrFalseQuestionList().add(tofQ);
        try {
            outputDataToFile(Database.DATABASE_PATH);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public synchronized static int[] deleteQuestions(List<Integer> ids, String type) {
        int id ;
        int removedCount = 0;
        List<?> list;
        if (type.equals("choice")) {
            list = database.getChoiceQuestionList();
        }else {
            list = database.getTrueOrFalseQuestionList();
        }
        for (Integer item : ids) {
            id = item - removedCount-1;
            if (id < list.size()) {
                System.out.println("删除了"+list.remove(id));
                removedCount++;
            }
            else break;
        }
        return new int[]{removedCount, ids.size()-removedCount};
    }

    public synchronized static int[] deleteUser(String[] usernameArr) {
        int deleteSuccessCount = 0;
        int deleteFailCount = 0;
        int adminCount = 0;
        for (String item : usernameArr) {
            int index;
            if ((index = database.getUserNameList().indexOf(item)) != -1) {
                if (database.getUserList().get(index) instanceof Student) {
                    database.getUserList().remove(index);
                    database.getUserNameList().remove(index);
                    deleteSuccessCount++;
                }else {
                    adminCount++;
                }
            }
            else deleteFailCount++;
        }
        return new int[]{deleteSuccessCount, deleteFailCount, adminCount};
    }

    public synchronized static int[] forceAddUser(List<Student> studentList) {
        int addSuccessCount = 0;
        int overrideCount = 0;
        int adminCount = 0;
        List<User> userInDatabase =  database.getUserList();
        for (Student item : studentList) {
            int index;
            if ((index = userInDatabase.indexOf(item)) != -1) {
                if (userInDatabase.get(index) instanceof Administrator) {
                    adminCount++;
                } else  {
                    userInDatabase.set(index, item);
                    overrideCount++;
                }
            } else {
                userInDatabase.add(item);
                database.getUserNameList().add(item.getUserName());
                addSuccessCount++;
            }
        }
        try {
            outputDataToFile(Database.DATABASE_PATH);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new int[]{addSuccessCount, overrideCount, adminCount};
    }

    public synchronized static void addUser(User user) throws UserIsExists {
        if (!database.getUserNameList().contains(user.getUserName())) {
            database.getUserList().add(user);
            database.getUserNameList().add(user.getUserName());
        }
        else {
            System.out.println("已存在的用户名:");
            database.getUserNameList().forEach(System.out::println);
            throw new UserIsExists();
        }
        try {
            outputDataToFile(Database.DATABASE_PATH);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public synchronized static void changeName(String userName, String newName) {
        int index = database.getUserList().indexOf(new User(userName));
        User user = database.getUserList().get(index);
        ((HaveName)user).setName(newName);
    }

    public synchronized static void changePassword(String userName, String newPassword) {
        int index = database.getUserList().indexOf(new User(userName));
        User user = database.getUserList().get(index);
        user.setPassword(newPassword);
    }

    public synchronized static List<HaveAnswer> getAllQuestions() {
        List<HaveAnswer> allQuestions = new ArrayList<>();
        allQuestions.addAll(database.getChoiceQuestionList());
        allQuestions.addAll(database.getTrueOrFalseQuestionList());
        return allQuestions;
    }
}
